# 1.server 例子
from socket import *
import time
ip_port=('localhost',51590)
bank_log=5
buffer_size=1024
tcp_server=socket(AF_INET,SOCK_STREAM)
tcp_server.bind(ip_port)
tcp_server.listen(bank_log)
print('waiting for connection...')
conn,addr = tcp_server.accept()
print("双向链接是",conn)
print("客户端地址",addr)
while True:
    data=conn.recv(buffer_size)
    print('server===>')
    print("客户端发来的消息是",data.decode("utf-8"))
    time.sleep(5)
    conn.sendall(data.upper())

conn.close()
tcp_server.close()
# ----------------阻塞IO循环收发消息----------
from socket import *
ip_port=("192.168.0.103",9006)
buffer_size=1024
back_log=5
sk=socket(AF_INET,SOCK_STREAM)
sk.bind(("192.168.0.103",8888))
sk.listen(5)
try:
    conn,addr = sk.accept()
    data=sk.recv(1024)
    print("双向链接是",conn)
    print("客户端地址",addr)
    print("客户端发来的消息是",data.decode("utf-8"))
    sk.send(data.upper())
    sk.close()
except Exception as e:
    print(e)

# -------------非阻塞IO----------------------
import socket,time
sk=socket.socket()
sk.bind(("192.168.0.103",8080))
sk.listen(5)
sk.setblocking(False)
print("waiting for connect.........")
while 1:
    try:
        conn,addr = sk.accept()
        print("连接地址：",addr)
        client_massage=conn.recv(1024)
        print(str(client_massage,"utf8"))
        conn.close()
    except Exception as e:
        print(e)
        time.sleep(3)

# ---------------select IO 多路复用----------------------
'''底层 select 实现'''
# import socket,time,select
# sk=socket.socket()
# # sk.bind(("192.168.0.103",8080))
# sk.bind(('localhost',5000))
# sk.listen(5)
# print("waiting for connect.........")
# while 1:
#     r,w,e = select.select([sk,],[],[],5)
#     for i in r:
#         conn, addr = i.accept()
#         print(conn)
#         print("hello")
#     print(">>>>>>>>>>>")

# ------------------------------------------------------
# import socket,time,select,selectors
# sk = socket.socket()
#
# sel = selectors.DefaultSelector()# select,pool,epool 操作系统自己选择一个
# sk.bind(('localhost',8090))
# sk.listen(5)
# sk.setblocking(False)
#
#
# def accept(socket,mask):
#     conn,addr = socket.accept()
#     print('accpeted',conn,"from",addr)
#     conn.setblocking(False) # 设置conn 为非阻塞
#
#
#     sel.register(conn,selectors.EVENT_READ,read)
# def read(conn,mask):
#     try:
#         data = conn.recv(100)
#         if not data:
#             raise Exception
#         conn.send(data)
#     except Exception as e:
#         print("close",conn)
#         sel.unregister(conn) # 解除注册绑定
#
# # sk.bind(("192.168.0.103",8080))
# sel.register(socket,selectors.EVENT_READ,accept) #注册socket与accept绑定
# while 1:
#     print("waiting for connect")
#     evevts = sel.select()#[socket,conn] 真正的监听
#     print(evevts)
#     for key,mask in evevts:
#         print(key)
#         print(mask)
#         callback = key.data # socket或者conn(key中绑定的函数)
#         callback(key.fileobj,mask) # 监听的对象
#     print(">>>>>>>>>>>")
import socket,time,select,selectors
import os
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
print(BASE_DIR)
class serverSelectors(object):
    def __init__(self):
        self.dict={}
        self.hasReceived=0
        self.sel = selectors.DefaultSelector() # select,pool,epool 操作系统自己选择一个
        self.create_socket()
        self.handle()

    def create_socket(self):
        sk = socket.socket()
        sk.bind(('localhost',1234))
        sk.listen(5)
        sk.setblocking(False)
        self.sel.register(sk,selectors.EVENT_READ,self.accept)
        print("服务器已启动成功、等待链接")

    def handle(self):
        while True:
            print("waiting for connect")
            evevts = self.sel.select()#[socket,conn] 真正的监听
            print(evevts)
            for key,mask in evevts:
                print(key)
                print(mask)
                callback = key.data # socket或者conn(key中绑定的函数)
                callback(key.fileobj,mask) # 监听的对象

    def accept(self,sock,mask):
        conn, addr = socket.accept()
        print('accpeted',conn,"from",addr)
        conn.setblocking(False) # 设置conn 为非阻塞
        self.sel.register(conn, selectors.EVENT_READ, self.read)

        self.dict[conn]={} # 空字典self.dict={conn1:{},conn2:{},...}

    def read(self,conn,make):
        # BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
        try:
            if not self.dict[conn]: # 是否是第一次创建
                data = conn.recv(1024)
                cmd,filename,filesize = str(data,encoding="utf-8").split("|")

                self.dict = {conn:{"cmd":cmd,"filename":filename,"filesize":int(filesize)}}

                if self.dict[conn][cmd] == "put":
                    conn.send(bytes("ok",encoding="utf-8"))

                if self.dict[conn][cmd] == "get":
                    file = os.path.join(BASE_DIR,"download",filename)
                    if os.path.exists(filename):
                        fileSize = os.path.getsize(file)
                        send_info = "%s|%s" %(filename,fileSize)
                        conn.send(bytes(send_info,encoding="utf-8"))
                    else:
                        send_info = "%s|%s" % ("NO file on server",0)
            else:
                if self.dict[conn].get("cmd",None):
                    cmd = self.dict[conn].get("cmd")
                    if hasattr(self,cmd):
                        func =getattr(self,cmd)
                        func(conn)
                    else:
                        print("error cmd")
        except Exception as e:
            print(e)
            self.sel.unregister(conn)
            conn.close()

    def put(self,conn):
        fileName =self.dict[conn].get("fileName")
        fileSize =self.dict[conn].get("fileSize")
        path = os.path.join(BASE_DIR,"upload",fileName)

        recv_dat = conn.recv(1024)
        self.hasReceived += len(recv_dat)

        with open(path,"ab") as f:
            f.write(recv_dat)
        if fileSize == self.hasReceived:
            if conn in self.dict.keys():
                self.dict[conn] = {}  # 文件上传完毕 conn1:{} 字典清空
                print("文件上传完毕",fileName)

    def get(self,conn):
        file = self.dict[conn].get("file")
        path = os.path.join(BASE_DIR, "download", file)
        with open(path, "ab") as f:
            for line in f:
                senf_data = f.read(line)
                conn.sendall(senf_data)


import socket,time,select
sk=socket.socket()
# sk.bind(("192.168.0.103",8080))
sk.bind(('localhost',5000))
sk.listen(5)
print("waiting for connect.........")
while 1:
    r,w,e = select.select([sk,],[],[],5)
    for i in r:
        conn, addr = i.accept()
        print(conn)
        print("hello")
    print(">>>>>>>>>>>")

# ------------------------------------------------------
import socket,time,select,selectors

class Selectors_server():
    sk = socket.socket()
    sel = selectors.DefaultSelector()  # select,pool,epool 操作系统自己选择一个
    sk.bind(('localhost', 8090))
    sk.listen(5)
    sk.setblocking(False)
    def accept(self,socket,mask):
        conn,addr = socket.accept()
        print('accpeted',conn,"from",addr)
        conn.setblocking(False) # 设置conn 为非阻塞
        self.sel.register(conn,selectors.EVENT_READ,self.read)

    def read(self,conn,mask):
        try:
            data = conn.recv(100)
            if not data:
                raise Exception
            conn.send(data)
        except Exception as e:
            print("close",conn)
            self.sel.unregister(conn) # 解除注册绑定

    sel.register(socket,selectors.EVENT_READ,accept) #注册socket与accept绑定
    while True:
        print("waiting for connect")
        evevts = sel.select()#[socket,conn] 真正的监听
        print(evevts)
        for key,mask in evevts:
            print(key)
            print(mask)
            callback = key.data # socket或者conn(key中绑定的函数)
            callback(key.fileobj,mask) # 监听的对象
        print(">>>>>>>>>>>")

if __name__ == '__main__':
    Selectors_server()

